import { App, PropType, defineComponent, computed, StyleValue } from 'vue'
import { JustifyContentProperty, AlignItemsProperty } from 'csstype'
import { filterEmpty } from '../_util/props-util'
import { useNameSpace } from '../_util/hooks'
import { castArray } from '../_util/_'

const prefixCls = 'x-space'

type Size = 'small' | 'medium' | 'large' | number | [number, number]

const Space = defineComponent({
  name: prefixCls,
  props: {
    size: { type: [Number, String, Array] as PropType<Size>, default: 'medium' },
    vertical: Boolean,
    wrap: { default: true },
    justify: String as PropType<JustifyContentProperty>,
    align: String as PropType<AlignItemsProperty>,
    itemStyle: [String, Object, Array] as PropType<StyleValue>
  },
  setup(props, { slots }) {
    const ns = useNameSpace(prefixCls)

    const sizeMap = {
      small: 8,
      medium: 12,
      large: 16
    }

    const gapStyle = computed(() => {
      const size = castArray(sizeMap[props.size as string] ?? props.size)
      return {
        marginRight: size[0] + 'px',
        marginBottom: (size[1] ?? size[0]) + 'px'
      }
    })

    return () => {
      const items = filterEmpty(slots.default?.())

      const cls = [
        prefixCls,
        {
          [ns.m('wrap')]: props.wrap,
          [ns.m('vertical')]: props.vertical
        }
      ]

      const style = {
        justifyContent: props.justify,
        alignItems: props.align,
        ...Object.fromEntries(Object.entries(gapStyle.value).map(e => [e[0], '-' + e[1]]))
      }

      return (
        <div class={cls} style={style}>
          {items.map(item => (
            <div class={ns.e('item')} style={[props.itemStyle, gapStyle.value]}>
              {item}
            </div>
          ))}
        </div>
      )
    }
  }
})

Space.install = (app: App) => {
  app.component(Space.name, Space)
}

export default Space
